package com.linkoog.devtools.project_manager.mac_tab;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
import com.intellij.openapi.wm.impl.ProjectFrameHelper;
import com.intellij.ui.mac.MacWinTabsHandler;
import com.intellij.ui.mac.MacWinTabsHandlerV2;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.intellij.ui.mac.foundation.MacUtil;
import com.linkoog.devtools.jdkEx.JdkEx;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


public class ProjectTabOpertion {

    public static boolean isTabbedWindow(@NotNull JFrame frame) {
        if (JdkEx.isTabbingModeAvailable() && WindowManager.getInstance().getAllProjectFrames().length > 1) {
            ID id = MacUtil.getWindowFromJavaWindow(frame);
            int tabs = Foundation.invoke(Foundation.invoke(id, "tabbedWindows"), "count").intValue();
            return tabs > 1;
        }
        return false;
    }

    public static void mergeAllWindows(@NotNull Window window) {
        IdeFrame[] frames = WindowManager.getInstance().getAllProjectFrames();
        if (frames.length > 1) {
            ID id = MacUtil.getWindowFromJavaWindow((((ProjectFrameHelper)frames[0]).getFrame()));
            int tabs = Foundation.invoke(Foundation.invoke(id, "tabbedWindows"), "count").intValue();
            if (frames.length != tabs){
                mergeAllWindows(window, true);
            }
        }
    }

    private static void mergeAllWindows(@NotNull Window window, boolean updateTabBars) {
        Foundation.executeOnMainThread(true, false, () -> {
            ID id = MacUtil.getWindowFromJavaWindow(window);
            Foundation.invoke(id, "mergeAllWindows:", ID.NIL);
            if (MacWinTabsHandler.isVersion2()) {
                ApplicationManager.getApplication().invokeLater(() -> {
                    try {
                        Method updateTabBarsAfterMerge = MacWinTabsHandlerV2.class.getDeclaredMethod("updateTabBarsAfterMerge");
                        updateTabBarsAfterMerge.setAccessible(true);
                        updateTabBarsAfterMerge.invoke(null );
                    } catch (NoSuchMethodException e) {
                    } catch (InvocationTargetException e) {
                    } catch (IllegalAccessException e) {
                    }
                });
            } else if (updateTabBars) {
                ApplicationManager.getApplication().invokeLater(() -> {
                    //MacWinTabsHandler.updateTabBars(null);
                    try {
                        Method updateTabBarsMethod = MacWinTabsHandler.class.getDeclaredMethod("updateTabBars", JFrame.class );
                        updateTabBarsMethod.setAccessible(true);
                        updateTabBarsMethod.invoke(null , (JFrame)null);
                    } catch (NoSuchMethodException e) {
                    } catch (InvocationTargetException e) {
                    } catch (IllegalAccessException e) {
                    }
                });
            }
        });
    }

    public static void disperseWindows() {
        IdeFrame[] frames = WindowManager.getInstance().getAllProjectFrames();
        if (frames.length > 1) {
            for (IdeFrame frame : frames) {
                ID id = MacUtil.getWindowFromJavaWindow((((ProjectFrameHelper)frame).getFrame()));
                int tabs = Foundation.invoke(Foundation.invoke(id, "tabbedWindows"), "count").intValue();
                if (tabs > 1){
                    disperseWindows(frame, true);
                }
            }
        }
    }

    private static void disperseWindows(@NotNull IdeFrame ideFrame, boolean updateTabBars) {
        Foundation.executeOnMainThread(true, false, () -> {
            ProjectFrameHelper frameHelper = (ProjectFrameHelper)ideFrame;
            ID id = MacUtil.getWindowFromJavaWindow(frameHelper.getFrame());
            Foundation.invoke(id, "moveTabToNewWindow:", ID.NIL);
            if (MacWinTabsHandler.isVersion2()) {
                ApplicationManager.getApplication().invokeLater(() ->  {
                    try {
                        Method updateTabBarsAfterMove = MacWinTabsHandlerV2.class.getDeclaredMethod("updateTabBarsAfterMove", IdeFrameImpl.class,IdeFrameImpl.class, int.class );
                        updateTabBarsAfterMove.setAccessible(true);
                        updateTabBarsAfterMove.invoke(null, frameHelper.getFrame(), null, -1);
                    } catch (NoSuchMethodException e) {
                    } catch (InvocationTargetException e) {
                    } catch (IllegalAccessException e) {
                    }
                });
            } else if (updateTabBars) {
                ApplicationManager.getApplication().invokeLater(() -> {
                    //MacWinTabsHandler.updateTabBars(null)
                    try {
                        Method updateTabBarsMethod = MacWinTabsHandler.class.getDeclaredMethod("updateTabBars", JFrame.class );
                        updateTabBarsMethod.setAccessible(true);
                        updateTabBarsMethod.invoke(null, (JFrame)null );
                    } catch (NoSuchMethodException e) {
                    } catch (InvocationTargetException e) {
                    } catch (IllegalAccessException e) {
                    }
                });
            }
        });
    }

    /**
     * //Select previous tab
     * class SelectPreviousTab : NSWindowAction("selectPreviousTab:")
     *
     * //Select next tab
     * //class SelectNextTab : NSWindowAction("selectNextTab:")
     *
     * //Move tab to a new window
     * //class MoveTabToNewWindow : NSWindowAction("moveTabToNewWindow:")
     *
     * //Merge all windows
     * //class MergeAllWindows : NSWindowAction("mergeAllWindows:")
     *
     * //Toggle tab bar
     * //class ToggleTabBar : NSWindowAction("toggleTabBar:")
     *
     * //Toggle tab overview
     * //class ToggleTabOverview : NSWindowAction("toggleTabOverview:")
     */
    public static void invokeFoundation(@NotNull String selector, Object... args) {
        ID app = Foundation.invoke("NSApplication", "sharedApplication");
        ID mainWindow = Foundation.invoke(app, Foundation.createSelector("mainWindow"));
        Foundation.invoke(mainWindow, Foundation.createSelector("performSelectorOnMainThread:withObject:waitUntilDone:"), Foundation.createSelector(selector), args, false);
    }

}
